#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2025/11/1 13:49
# @Author  : summer
# @Email   : 610658552@qq.com
# @File    : view_sms.py
# @Software: PyCharm
# @Desc    : 多手机号短信发送（逐个发送+批量日志）

import logging

from rest_framework.exceptions import ValidationError
from rest_framework.generics import GenericAPIView

from common.utils.rsp import success_response
from push.sers.ser_sms import SMSSendSerializer
from ssms import models
from ssms.models import SMSLog
from ssms.utils.util_aliyun import AliYunSMS

# 初始化业务日志器
logger = logging.getLogger('business')


class SMSSendView(GenericAPIView):
    serializer_class = SMSSendSerializer  # 指定序列化器，复用DRF的get_serializer方法

    def post(self, request, pk):
        # 1. 日志记录请求入口（含关键上下文）
        client_ip = request.META.get('REMOTE_ADDR', '未知IP')
        logger.info(f"接收单个短信发送请求 | 模板ID: {pk} | 客户端IP: {client_ip} | 请求数据: {request.data}")

        try:
            # 2. 序列化器校验（完全依赖序列化器，删除手动校验phone/send_data）
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            validated_data = serializer.validated_data  # 校验后的数据直接用，无需再从request.data取
            logger.debug(f"请求参数校验通过 | 校验后数据: {validated_data}")

            # 3. 提取参数（从校验后的数据取，确保类型/格式合法）
            mobile = validated_data["phone"]  # 已确保是11位数字字符串（序列化器处理过）
            content = validated_data["send_data"]  # 已确保是字典（默认空字典）

            # 4. 查询短信模板（捕获模板不存在异常，返回明确错误）
            logger.debug(f"查询短信模板 | 模板ID: {pk}")
            try:
                sms_template = models.SMSTemplate.objects.get(
                    pk=pk,
                    is_delete=0,  # 仅查询未删除的模板
                    pt_flag=0,  # 排除压测数据
                    is_active=1  # 仅查询启用的模板
                )
            except models.SMSTemplate.DoesNotExist:
                err_msg = f"短信模板不存在（ID: {pk}）"
                logger.error(err_msg)
                raise ValidationError({"error": err_msg})
            logger.info(f"模板查询成功 | ID: {pk} | 签名: {sms_template.sign} | 模板CODE: {sms_template.template_id}")

            # 5. 初始化阿里云短信客户端 & 发送短信
            logger.debug(f"初始化短信客户端 | 供应商: {sms_template.sms_provider.sms_name}")
            sms = AliYunSMS(
                sms_key=sms_template.sms_provider.sms_key,
                sms_secret=sms_template.sms_provider.sms_secret
            )

            logger.info(f"开始发送短信 | 手机号: {mobile} | 模板CODE: {sms_template.template_id}")
            result = sms.send_sms(
                mobile=mobile,
                sign_name=sms_template.sign,
                template_code=sms_template.template_id,
                template_param=content
            )
            logger.debug(f"短信接口返回结果 | 手机号: {mobile} | 结果: {result}")

            # 6. 解析发送结果 & 记录数据库日志
            ret_success = result.get("success", False)
            message = result.get("message", "无返回信息")
            request_id = result.get("request_id", "")  # 阿里云请求ID，便于对账/报障
            # 构造日志内容（成功显式内容，失败显式错误原因）
            sms_content = (
                f"模板ID：{sms_template.template_id}，发送内容：{content}，请求ID：{request_id}"
                if ret_success else f"发送失败：{message}，请求ID：{request_id}"
            )

            # 写入发送日志
            SMSLog.objects.create(
                phone=mobile,
                sign=sms_template.sign,
                template_id=sms_template.template_id,
                content=sms_content,
                is_send=1 if ret_success else 0
            )
            logger.info(f"短信发送{'成功' if ret_success else '失败'} | 手机号: {mobile} | 请求ID: {request_id}")

            # 7. 返回响应（携带请求ID，方便后续追溯）
            return success_response(
                success=ret_success,
                message=message,
                data={"request_id": request_id}  # 返回阿里云请求ID，便于问题定位
            )

        # 8. 捕获未知异常（避免接口崩溃，记录完整堆栈）
        except Exception as e:
            err_msg = f"单个短信发送流程异常：{str(e)}"
            logger.error(err_msg, exc_info=True)  # exc_info=True 记录堆栈，便于调试
            raise  # 抛出异常由DRF统一处理（返回500+错误信息）
